# Copyright (c) 2021-2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

panda_promote_to_definitions(PANDA_ECMASCRIPT_ENABLE_RUNTIME_STAT)

add_subdirectory(builtins)

set(ECMA_SRC_DIR ${PANDA_ECMASCRIPT_PLUGIN_SOURCE}/runtime)

if(PANDA_TARGET_ARM32)
    SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/arm/builtin_bridge_arm.S)
elseif(PANDA_TARGET_ARM64)
    SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/aarch64/builtin_bridge_aarch64.S)
elseif(PANDA_TARGET_X86)
elseif(PANDA_TARGET_AMD64)
    SET(BUILTIN_BRIDGE_SOURCE ${ECMA_SRC_DIR}/bridge/arch/amd64/builtin_bridge_amd64.S)
endif()

set(ECMA_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
file(MAKE_DIRECTORY "${ECMA_GEN_DIR}")

set(ECMASCRIPT_SOURCES
    ${ECMA_SRC_DIR}/bridge/ecma_bridge_helpers.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_collator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_date_time_format.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_intl.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_locale.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_number_format.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_plural_rules.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_relative_time_format.cpp
    ${ECMA_SRC_DIR}/js_collator.cpp
    ${ECMA_SRC_DIR}/js_date_time_format.cpp
    ${ECMA_SRC_DIR}/js_locale.cpp
    ${ECMA_SRC_DIR}/js_number_format.cpp
    ${ECMA_SRC_DIR}/js_plural_rules.cpp
    ${ECMA_SRC_DIR}/js_relative_time_format.cpp
    ${ECMA_SRC_DIR}/base/array_helper.cpp
    ${ECMA_SRC_DIR}/base/builtins_base.cpp
    ${ECMA_SRC_DIR}/base/error_helper.cpp
    ${ECMA_SRC_DIR}/base/json_parser.cpp
    ${ECMA_SRC_DIR}/base/json_stringifier.cpp
    ${ECMA_SRC_DIR}/base/number_helper.cpp
    ${ECMA_SRC_DIR}/base/object_helper.cpp
    ${ECMA_SRC_DIR}/base/string_helper.cpp
    ${ECMA_SRC_DIR}/base/typed_array_helper.cpp
    ${ECMA_SRC_DIR}/builtins.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_ark_tools.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_array.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_arraybuffer.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_async_function.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_async_from_sync_iterator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_async_generator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_async_iterator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_bigint.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_boolean.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_dataview.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_date.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_errors.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_function.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_generator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_global.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_iterator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_json.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_map.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_math.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_number.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_object.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_promise.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_promise_handler.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_promise_job.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_proxy.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_reflect.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_regexp.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_runtime_testing.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_set.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_string.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_string_iterator.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_symbol.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_typedarray.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_weak_ref.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_weak_map.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_weak_set.cpp
    ${ECMA_SRC_DIR}/builtins/builtins_finalization_registry.cpp
    ${ECMA_SRC_DIR}/class_linker/panda_file_translator.cpp
    ${ECMA_SRC_DIR}/containers/containers_arraylist.cpp
    ${ECMA_SRC_DIR}/containers/containers_private.cpp
    ${ECMA_SRC_DIR}/dump.cpp
    ${ECMA_SRC_DIR}/ecma_call_profiling_table.cpp
    ${ECMA_SRC_DIR}/ecma_class_linker_extension.cpp
    ${ECMA_SRC_DIR}/ecma_compiler.cpp
    ${ECMA_SRC_DIR}/ecma_entrypoints.cpp
    ${ECMA_SRC_DIR}/ecma_exceptions.cpp
    ${ECMA_SRC_DIR}/ecma_language_context.cpp
    ${ECMA_SRC_DIR}/ecma_module.cpp
    ${ECMA_SRC_DIR}/ecma_profiling.cpp
    ${ECMA_SRC_DIR}/ecma_string.cpp
    ${ECMA_SRC_DIR}/ecma_string_table.cpp
    ${ECMA_SRC_DIR}/ecma_vm.cpp
    ${ECMA_SRC_DIR}/free_object.cpp
    ${ECMA_SRC_DIR}/generator_helper.cpp
    ${ECMA_SRC_DIR}/global_env.cpp
    ${ECMA_SRC_DIR}/global_env_constants.cpp
    ${ECMA_SRC_DIR}/ic/profile_type_info.cpp
    ${ECMA_SRC_DIR}/ic/ic_runtime.cpp
    ${ECMA_SRC_DIR}/ic/ic_runtime_stub.cpp
    ${ECMA_SRC_DIR}/ic/property_box.cpp
    ${ECMA_SRC_DIR}/ic/proto_change_details.cpp
    ${ECMA_SRC_DIR}/internal_call_params.cpp
    ${ECMA_SRC_DIR}/interpreter/slow_runtime_helper.cpp
    ${ECMA_SRC_DIR}/interpreter/slow_runtime_stub.cpp
    ${ECMA_SRC_DIR}/intrinsics.cpp
    ${ECMA_SRC_DIR}/jobs/micro_job_queue.cpp
    ${ECMA_SRC_DIR}/js_arguments.cpp
    ${ECMA_SRC_DIR}/js_array.cpp
    ${ECMA_SRC_DIR}/js_array_iterator.cpp
    ${ECMA_SRC_DIR}/js_arraybuffer.cpp
    ${ECMA_SRC_DIR}/js_arraylist.cpp
    ${ECMA_SRC_DIR}/js_async_from_sync_iterator_object.cpp
    ${ECMA_SRC_DIR}/js_async_function.cpp
    ${ECMA_SRC_DIR}/js_async_generator_object.cpp
    ${ECMA_SRC_DIR}/js_bigint.cpp
    ${ECMA_SRC_DIR}/js_dataview.cpp
    ${ECMA_SRC_DIR}/js_date.cpp
    ${ECMA_SRC_DIR}/js_eval.cpp
    ${ECMA_SRC_DIR}/js_for_in_iterator.cpp
    ${ECMA_SRC_DIR}/js_function.cpp
    ${ECMA_SRC_DIR}/js_generator_object.cpp
    ${ECMA_SRC_DIR}/js_hclass.cpp
    ${ECMA_SRC_DIR}/js_invoker.cpp
    ${ECMA_SRC_DIR}/js_iterator.cpp
    ${ECMA_SRC_DIR}/js_map.cpp
    ${ECMA_SRC_DIR}/js_map_iterator.cpp
    ${ECMA_SRC_DIR}/js_method.cpp
    ${ECMA_SRC_DIR}/js_object.cpp
    ${ECMA_SRC_DIR}/js_primitive_ref.cpp
    ${ECMA_SRC_DIR}/js_promise.cpp
    ${ECMA_SRC_DIR}/js_proxy.cpp
    ${ECMA_SRC_DIR}/js_regexp_iterator.cpp
    ${ECMA_SRC_DIR}/js_serializer.cpp
    ${ECMA_SRC_DIR}/js_set.cpp
    ${ECMA_SRC_DIR}/js_set_iterator.cpp
    ${ECMA_SRC_DIR}/js_stable_array.cpp
    ${ECMA_SRC_DIR}/js_string_iterator.cpp
    ${ECMA_SRC_DIR}/js_tagged_value.cpp
    ${ECMA_SRC_DIR}/js_thread.cpp
    ${ECMA_SRC_DIR}/js_typed_array.cpp
    ${ECMA_SRC_DIR}/js_weak_container.cpp
    ${ECMA_SRC_DIR}/js_finalization_registry.cpp
    ${ECMA_SRC_DIR}/linked_hash_table.cpp
    ${ECMA_SRC_DIR}/literal_data_extractor.cpp
    ${ECMA_SRC_DIR}/message_string.cpp
    ${ECMA_SRC_DIR}/mem/ecma_reference_processor.cpp
    ${ECMA_SRC_DIR}/mem/ecma_string.cpp
    ${ECMA_SRC_DIR}/mem/mem_manager.cpp
    ${ECMA_SRC_DIR}/napi/jsnapi.cpp
    ${ECMA_SRC_DIR}/napi/jsnapi_debugger_agent.cpp
    ${ECMA_SRC_DIR}/object_factory.cpp
    ${ECMA_SRC_DIR}/object_operator.cpp
    ${ECMA_SRC_DIR}/layout_info.cpp
    ${ECMA_SRC_DIR}/regexp/regexp_executor.cpp
    ${ECMA_SRC_DIR}/regexp/regexp_parser_cache.cpp
    ${ECMA_SRC_DIR}/tagged_dictionary.cpp
    ${ECMA_SRC_DIR}/template_string.cpp
    ${ECMA_SRC_DIR}/vmstat/caller_stat.cpp
    ${ECMA_SRC_DIR}/vmstat/runtime_stat.cpp
    ${ECMA_SRC_DIR}/weak_vector.cpp
    ${ECMA_SRC_DIR}/class_info_extractor.cpp

    ${ECMA_SRC_DIR}/compiler/ecmascript_runtime_interface.cpp
    ${BUILTIN_BRIDGE_SOURCE}

    ${ECMA_SRC_DIR}/tooling/pt_ecmascript_extension.cpp
)

add_dependencies(arkruntime_obj ecmastdlib_inline_h)

set(IRTOC_ECMASCRIPT_SCRIPTS ${PANDA_ROOT}/plugins/ecmascript/irtoc_scripts)
set(IRTOC_ECMASCRIPT_SCRIPTS ${IRTOC_ECMASCRIPT_SCRIPTS} PARENT_SCOPE)
if(NOT (CMAKE_CROSSCOMPILING OR PANDA_TARGET_OHOS))
    irtoc_compile(TARGET_NAME irtoc_ecmascript_fastpath
                  INPUT_FILES ${IRTOC_ECMASCRIPT_SCRIPTS}/object.irt
                              ${IRTOC_ECMASCRIPT_SCRIPTS}/new_obj_dyn.irt
                  TARGET_VARIABLE IRTOC_ECMASCRIPT_FASTPATH_OBJ)

    if (NOT EXISTS ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
        file(TOUCH ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
    endif()
    set(irtoc_ecmascript_fastpath_target irtoc_ecmascript_fastpath)
else()
    ExternalProject_Get_Property(panda_host_tools binary_dir)
    set(IRTOC_ECMASCRIPT_FASTPATH_OBJ "${binary_dir}/irtoc/irtoc_ecmascript_fastpath/irtoc_ecmascript_fastpath.o")

    SET_SOURCE_FILES_PROPERTIES(${IRTOC_ECMASCRIPT_FASTPATH_OBJ} PROPERTIES
        EXTERNAL_OBJECT true
        GENERATED true
    )

    # Due to cmake complain about absence of the irtoc file, we just fake it until it will be generated
    file(MAKE_DIRECTORY ${binary_dir}/irtoc/irtoc_ecmascript_fastpath)
    if (NOT EXISTS ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
        file(TOUCH ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
    endif()
    set(irtoc_ecmascript_fastpath_target panda_host_tools-build)
endif()

add_dependencies(arkruntime_obj
    ${irtoc_ecmascript_fastpath_target}
)

panda_target_sources(arkruntime_obj PRIVATE ${ECMASCRIPT_SOURCES})
panda_target_sources(arkruntime_interpreter_static PRIVATE ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
panda_target_sources(arkruntime_static PRIVATE ${IRTOC_ECMASCRIPT_FASTPATH_OBJ})
panda_target_include_directories(arkruntime_obj PUBLIC
     ${PANDA_ECMASCRIPT_PLUGIN_SOURCE}/runtime
     ${PANDA_BINARY_ROOT}/compiler/generated
     ${PANDA_BINARY_ROOT}/plugins/ecmascript/ecmastdlib
     ${PANDA_BINARY_ROOT}/tools/es2panda
     ${ES2PANDA_PATH}
     ${ECMA_GEN_DIR}
)

panda_target_link_libraries(arkruntime_obj es2panda-public arkassembler)

set(RUNTIME_TEMPLATES
    intrinsics_gen.cpp.erb
)

panda_gen(
    DATA
        ${ECMA_SRC_DIR}/ecma_runtime.yaml
        ${ECMA_SRC_DIR}/ecma_runtime.yaml
    TARGET_NAME ecma_intrinsics_gen_arkruntime
    TEMPLATES ${RUNTIME_TEMPLATES}
    API
        ${CMAKE_SOURCE_DIR}/runtime/templates/intrinsics.rb
        ${CMAKE_SOURCE_DIR}/runtime/templates/runtime.rb
    REQUIRES ${PANDA_ROOT}/libpandabase/utils.rb
    SOURCE ${ECMA_SRC_DIR}/templates
    DESTINATION ${ECMA_GEN_DIR}
)

add_dependencies(arkruntime_obj ecma_intrinsics_gen_arkruntime)
add_dependencies(intrinsics_gen_arkruntime ecma_intrinsics_gen_arkruntime)

panda_target_include_directories(arkruntime_interpreter_impl PUBLIC
    ${PANDA_BINARY_ROOT}/compiler/generated
)

if (TARGET arkruntime_test_interpreter_impl)
    panda_target_include_directories(arkruntime_test_interpreter_impl PUBLIC
        ${PANDA_BINARY_ROOT}/compiler/generated
    )
endif()

add_dependencies(arkruntime_interpreter_impl arkcompiler)

set_source_files_properties(${ECMASCRIPT_SOURCES} PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)

set_source_files_properties(${ECMA_SRC_DIR}/js_locale.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/js_date_time_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/js_relative_time_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/js_number_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/global_env.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/ecma_vm.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)

set_source_files_properties(${ECMA_SRC_DIR}/builtins.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_string.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_locale.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_intl.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_number_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_number.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_relative_time_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_date.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)
set_source_files_properties(${ECMA_SRC_DIR}/builtins/builtins_date_time_format.cpp PROPERTIES COMPILE_FLAGS -Wno-shadow)

add_merge_plugin(PLUGIN_NAME "read_profile.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_read_profile.h")
add_merge_plugin(PLUGIN_NAME "destroy_profile.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_destroy_profile.h")
add_merge_plugin(PLUGIN_NAME "find_method_in_profile.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_find_method_in_profile.h")
add_merge_plugin(PLUGIN_NAME "dump_profile.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_dump_profile.h")
add_merge_plugin(PLUGIN_NAME "clear_profile.h"
                INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_clear_profile.h")
add_merge_plugin(PLUGIN_NAME "profiling_includes.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_includes.h")
add_merge_plugin(PLUGIN_NAME "profiling_includes_disasm.h"
        INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/profiling/plugin_includes_disasm.h")
